#include "stdafx.h"
#include "symulator.h"
#include "konfiguracja.h"
#include <algorithm>
#include "generatory.h"


std::vector<ObiektDyskretny *> zbiorDyskr;


Symulator::Symulator(System::Windows::Forms::Form^ parent) : obiektUstawiony(false) {
   this->parent = parent;
   petla = new PetlaSymulacji();
   autoryzacja = gcnew AutoryzacjaDostepu();
   //   wektorRegulatorow = new std::vector<int>();
   //   wektorObiektow = new std::vector<int>();
   std::map<std::string,int> wektor = Generator::pobierzDostepneGeneratory();
   std::map<std::string,int>::iterator it = wektor.begin();

   for(; it != wektor.end(); ++it) {
      mapaPustychGeneratorow[ToSysString(it->first)] = it->second;
   }

}

Symulator::~Symulator() {

}

void Symulator::wczytajKonfiguracje() {
   //   usunDyskretne();
   try {
      zbiorDyskr = PlikKonfiguracyjny::pobierzInstancje().wczytaj();

   } catch (...) {
      
   }

   for (int i = 0; i != zbiorDyskr.size(); i++) {
      // --- mamy regulator ---------------------------------------------------------
      Regulator *reg = dynamic_cast<Regulator * > (zbiorDyskr.at(i));
      if (reg) {
	 mapaRegulatorow[ToSysString(zbiorDyskr.at(i)->pobierzNazwe())] = (zbiorDyskr.at(i)->getID());
      }
	
      // ---- mamy ObiektARMAX ---------------------------------------------------------
      ObiektARMAX *ob = dynamic_cast<ObiektARMAX * > (zbiorDyskr.at(i));
      if (ob) {
	 mapaObiektow[ToSysString(zbiorDyskr.at(i)->pobierzNazwe())] = (zbiorDyskr.at(i)->getID());
      }      
   }
   nowyStan(TematAktualizacji::nowaMapaRegulatorow);
   nowyStan(TematAktualizacji::nowaMapaObiektow);
   nowyStan(TematAktualizacji::nowaMapaWartZad);
}

void Symulator::symulatorStart(Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      if(!watekSymulacji) {
	 watekSymulacji = gcnew System::Threading::Thread( gcnew System::Threading::ThreadStart(this,&Symulator::petlaSymulacji));
	 watekSymulacji->Start();
      } else {
	 if(!watekSymulacji->IsAlive) {
	    watekSymulacji = gcnew System::Threading::Thread( gcnew System::Threading::ThreadStart(this,&Symulator::petlaSymulacji));
	    watekSymulacji->Start();
	 }
      }
   }
}
      

void Symulator::symulatorStop(Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      if (watekSymulacji) {
	 watekSymulacji->Abort();
	 //delete watekSymulacji;
      }
   }
}

void Symulator::symulatorReset(Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      if (watekSymulacji) {
	 watekSymulacji->Abort();
	 //delete watekSymulacji;
	 nowyStan(resetSymulacji);
      }
      petla->reset();
      u = 0;
      y = 0;
    }
}

System::Void Symulator::petlaSymulacji() {
   nowyStan_d^ nowyStanDelegat = gcnew nowyStan_d(this, &Symulator::nowyStan);
   while (true) {
      
      petla->wykonajKrokSymulacji();
      tablicaWartosci.clear();
      tablicaWartosci.push_back(petla->pobierzCzas());
      tablicaWartosci.push_back(petla->pobierzWartoscRegulowana());
      tablicaWartosci.push_back(petla->pobierzWartoscZadana());
      tablicaWartosci.push_back(petla->pobierzSterowanie());
      /* u = petla->pobierzSterowanie();
      y = petla->pobierzWartoscRegulowana();
      w = petla->pobierzWartoscZadana();
      czas = */
      
      //tablicaWartosci = gcnew array <System::Object^>(4) {czas, y, w, u};
      parent->Invoke(nowyStanDelegat,gcnew array<System::Object^>(1){static_cast<int>(TematAktualizacji::nowyKrokSymulacji)});      
      nrProbki++;
      /*RegulatorPIDAdapt* regulatorPIDAdaptPtr = dynamic_cast<RegulatorPIDAdapt*>(petla->);
      if (regulatorPIDAdaptPtr != NULL &&
	  regulatorPIDAdaptPtr->czyKoniecSamonastrajania()) {
	 this->Invoke(aktywujSamonastrajanie, gcnew array<System::Boolean^>(1) {
               true
		  });
		  }*/

      Thread::Sleep(czasProbkowania);
   }
}

void Symulator::dodajObserwatora(Obserwator^ ob) {
   listaObserwatorow.push_back(ob);
}

void Symulator::usunObserwatora(Obserwator^ ob) {
   listaObserwatorow.remove(ob);
}

void Symulator::nowyStan(int zdarzenie) {
   cliext::list<Obserwator^>::iterator it = listaObserwatorow.begin();
   for(; it != listaObserwatorow.end(); ++it) {
      it->aktualizuj(zdarzenie);
   }
}

cliext::map<System::String^,int> Symulator::pobierzMapeRegulatorow() {
   return mapaRegulatorow;
}

cliext::map<System::String^,int> Symulator::pobierzMapeObiektow() {
   return mapaObiektow;
}

cliext::map<System::String^, int> Symulator::pobierzMapeWartZad() {
   return mapaPustychGeneratorow;
}

cliext::vector<System::String^> Symulator::pobierzListeUstawionychGeneratorow() {
   return wektorDodanychGeneratorow;
}

void Symulator::ustawRegulator(System::String^ nazwa, Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      cliext::map<System::String^, int>::iterator mapIt = mapaRegulatorow.find(nazwa);
      if(mapIt != mapaRegulatorow.end()){
	 PorownajWskaznikZInt<Kolekcja> idRegulatora = {mapIt->second};
   
	 try {
	    petla->ustawRegulator(*(find_if(zbiorDyskr.begin(), zbiorDyskr.end(), idRegulatora)));
	    nowyStan(TematAktualizacji::zmianaRegulatora);
	 } catch(...) {
	    //moze_gdzies_to_zapisac
	 }
      }
   } 
}

void Symulator::ustawObiekt(System::String^ nazwa, Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      cliext::map<System::String^, int>::iterator mapIt = mapaObiektow.find(nazwa);
      if(mapIt != mapaObiektow.end()){
	 PorownajWskaznikZInt<Kolekcja> idObiektu = {mapIt->second};
	 std::vector<ObiektDyskretny*>::iterator it;
	 try {
	    if(obiektUstawiony) {
	       petla->usunObiekt(1); //symulator ograniczna mozliwosc nieskonczonej liczby obiektow
	    }
	    if((it = find_if(zbiorDyskr.begin(), zbiorDyskr.end(), idObiektu)) != zbiorDyskr.end()) {
	       petla->dodajObiekt(*(find_if(zbiorDyskr.begin(), zbiorDyskr.end(), idObiektu)));
	       nowyStan(TematAktualizacji::zmianaObiektu);
	       obiektUstawiony = true;
	    }
	 } catch(...) {
	    //moze_gdzies_to_zapisac
	 }
      }
   }
}

void Symulator::dodajWartZad(System::String^ nazwa, Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      cliext::map<System::String^, int>::iterator mapIt = mapaPustychGeneratorow.find(nazwa);
      if(mapIt != mapaPustychGeneratorow.end()){
	 switch(mapIt->second) {
	 case Generatory::Losowy:
	    petla->dodajGenerator(new GeneratorLosowy());
	    break;

	 case Generatory::Trojkat:
	    petla->dodajGenerator(new GeneratorTrojkata());
	    break;

	 case Generatory::Sinus:
	    petla->dodajGenerator(new GeneratorSinusa());
	    break;

	 case Generatory::Impuls:
	    petla->dodajGenerator(new GeneratorImpulsu());
	    break;

	 case Generatory::Prostokat:
	    petla->dodajGenerator(new GeneratorProstokata());
	    break;
      
      
	 case Generatory::Skok:
	    petla->dodajGenerator(new GeneratorSkoku());
	    break;
	 }
	 aktualizacjaListyGeneratorowSymulatora();
	 nowyStan(TematAktualizacji::nowaListaUstawionychGeneratorow);
      }
   }
}

void Symulator::aktualizacjaListyGeneratorowSymulatora() {

      std::vector<std::string> generatory = petla->pokazUstawioneGeneratory();
      std::vector<std::string>::iterator it = generatory.begin();
      wektorDodanychGeneratorow.clear();
      for(; it != generatory.end(); ++it) {
	 wektorDodanychGeneratorow.push_back(ToSysString(*it));
      }   

}

void Symulator::usunWartZad(System::String^ nazwa, Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {

   }
}



std::map<std::string, std::string> Symulator::pobierzKonfigRegulatora() {   
   return petla->pobierzKonfigRegulatora();
}

std::map<std::string, std::string> Symulator::pobierzKonfigObiektu() {   
   return petla->pobierzKonfigObiektu();
}

std::map<std::string, std::string> Symulator::pobierzKonfigGeneratora(std::string nazwa) {
   return petla->pobierzKonfigWartZad(nazwa);
}

cliext::vector<double> Symulator::pobierzAktualneWartosci() {
   return tablicaWartosci;
}

void Symulator::ustawCzasProbkowania(int czasProbkowania, Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      this->czasProbkowania = czasProbkowania;
   }
}

void Symulator::zmienParametryRegulatora(std::map<std::string,
						  std::string> konfig,
					 Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      if(petla->ustawParametryObiektu(konfig)) {
	 nowyStan(TematAktualizacji::zmianaRegulatora);
      }
   }
}

void Symulator::zmienParametryGeneratora(std::string nazwa,
					 std::map<std::string,
						  std::string> konfig,
					 Autoryzowany^ obiekt, int deskr) {
   if(autoryzacja->czyAutoryzowany(obiekt,deskr)) {
      petla->ustawParametryGeneratora(nazwa,konfig);
   }
}

void Symulator::ustawAutoryzowanySerwer(Autoryzowany^ obiekt) {
   autoryzacja->ustawSerwer(obiekt);
}

void Symulator::ustawAutoryzowaneGUI(Autoryzowany^ obiekt) {
   autoryzacja->ustawGUI(obiekt);
}


int Symulator::zaloguj(int id, std::string login, std::string haslo) {
	return autoryzacja->zaloguj(id, login, haslo);
}

void Symulator::wyloguj(int id) {
	autoryzacja->wyloguj(id);
}